﻿using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using IssueVision.Common;
using IssueVision.EntityModel;
using SL.IdentityModel.Services;

namespace IssueVision.ViewModel
{
    [Export(ViewModelTypes.NewIssueViewModel, typeof(ViewModelBase))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class NewIssueViewModel : ViewModelBase
    {
        #region "Private Data Members"
        private IIssueVisionModel _issueVisionModel;
        #endregion "Private Data Members"

        #region "Constructor"
        [ImportingConstructor]
        public NewIssueViewModel(IIssueVisionModel issueVisionModel)
        {
            _issueVisionModel = issueVisionModel;

            // Set up event handling
            _issueVisionModel.SaveChangesCompleted += _issueVisionModel_SaveChangesCompleted;
            _issueVisionModel.PropertyChanged += _issueVisionModel_PropertyChanged;

            // initiate a new issue
            CurrentIssue = AddNewIssue();
            AppMessages.EditIssueMessage.Send(CurrentIssue);
        }
        #endregion "Constructor"

        #region "ICleanup interface implementation"
        public override void Cleanup()
        {
            if (_issueVisionModel != null)
            {
                // unregister all events
                _issueVisionModel.SaveChangesCompleted -= _issueVisionModel_SaveChangesCompleted;
                _issueVisionModel.PropertyChanged -= _issueVisionModel_PropertyChanged;
                 //set CurrentIssue back to null
                CurrentIssue = null;
                // set _issueVisionModel to null
                _issueVisionModel = null;
            }
            // unregister any messages for this ViewModel
            base.Cleanup();
        }
        #endregion "ICleanup interface implementation"

        #region "Public Properties"

        public Issue CurrentIssue
        {
            get
            {
                return _issueVisionModel != null ? _issueVisionModel.CurrentEditIssue : null;
            }
            private set
            {
                if (_issueVisionModel != null)
                {
                    if (!ReferenceEquals(_issueVisionModel.CurrentEditIssue, value))
                    {
                        // update CurrentEditIssue on the model
                        _issueVisionModel.CurrentEditIssue = value;
                        RaisePropertyChanged("CurrentIssue");
                    }
                }
            }
        }

        #endregion "Public Properties"

        #region "Public Commands"

        private RelayCommand _submitChangeCommand;

        public RelayCommand SubmitChangeCommand
        {
            get
            {
                if (_submitChangeCommand == null)
                {
                    _submitChangeCommand = new RelayCommand(
                        () => OnSubmitChangeCommand(),
                        () => (_issueVisionModel != null) && (_issueVisionModel.HasChanges));
                }
                return _submitChangeCommand;
            }
        }

        private void OnSubmitChangeCommand()
        {
            try
            {
                if (!_issueVisionModel.IsBusy)
                {
                    if (CurrentIssue != null)
                    {
                        // if status is Open, AssignedToID should be null
                        if (CurrentIssue.StatusID == IssueVisionServiceConstant.OpenStatusID)
                        {
                            CurrentIssue.AssignedToID = null;
                        }
                        // set ResolutionDate and ResolvedByID based on ResolutionID
                        if (CurrentIssue.ResolutionID == null || CurrentIssue.ResolutionID == 0)
                        {
                            CurrentIssue.ResolutionDate = null;
                            CurrentIssue.ResolvedByID = null;
                        }
                        else
                        {
                            if (CurrentIssue.ResolutionDate == null)
                                CurrentIssue.ResolutionDate = DateTime.Now;
                            if (CurrentIssue.ResolvedByID == null)
                                CurrentIssue.ResolvedByID = ClaimsIdentitySessionManager.Current.User.Identity.Name;
                        }
                        if (CurrentIssue.TryValidate())
                            _issueVisionModel.SaveChangesAsync();
                    }
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        private RelayCommand _cancelChangeCommand;

        public RelayCommand CancelChangeCommand
        {
            get
            {
                if (_cancelChangeCommand == null)
                {
                    _cancelChangeCommand = new RelayCommand(
                        () => OnCancelChangeCommand(),
                        () => (_issueVisionModel != null) && (_issueVisionModel.HasChanges));
                }
                return _cancelChangeCommand;
            }
        }

        private void OnCancelChangeCommand()
        {
            try
            {
                MessageBoxResult theResult = MessageBoxResult.Cancel;

                if (!_issueVisionModel.IsBusy)
                {
                    // ask to confirm canceling this new issue first
                    DialogMessage dialogMessage = new DialogMessage(
                        this,
                        CommonResources.CancelCurrentIssueMessageBoxText,
                        s => theResult = s)
                    {
                        Button = MessageBoxButton.OKCancel,
                        Caption = CommonResources.ConfirmMessageBoxCaption
                    };

                    AppMessages.PleaseConfirmMessage.Send(dialogMessage);

                    if (theResult == MessageBoxResult.OK)
                    {
                        // if confirmed, cancel this issue
                        _issueVisionModel.RejectChanges();
                        // initiate a new issue again
                        CurrentIssue = AddNewIssue();
                        AppMessages.EditIssueMessage.Send(CurrentIssue);
                    }
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        #endregion "Public Commands"

        #region "Private Methods"

        /// <summary>
        /// Function to create a new issue
        /// </summary>
        /// <returns></returns>
        private static Issue AddNewIssue()
        {
            Issue g = new Issue
            {
                IssueID = 0,
                OpenedDate = DateTime.Now,
                OpenedByID = ClaimsIdentitySessionManager.Current.User.Identity.Name,
                LastChange = DateTime.Now,
                ChangedByID = ClaimsIdentitySessionManager.Current.User.Identity.Name,
                AssignedToID = null,
                Priority = 2,
                Severity = 2,
                StatusID = 0,
                SubStatusID = null
            };

            return g;
        }

        /// <summary>
        /// Event handler for SaveChangesCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_SaveChangesCompleted(object sender, ResultArgs<string> e)
        {
            if (!e.HasError)
            {
                // check whether there is any warning message returned
                if (!string.IsNullOrEmpty(e.Results))
                {
                    DialogMessage dialogMessage = new DialogMessage(
                        this,
                        e.Results,
                        null)
                    {
                        Button = MessageBoxButton.OK,
                        Caption = CommonResources.WarningMessageBoxCaption
                    };

                    AppMessages.StatusUpdateMessage.Send(dialogMessage);
                }
                else
                {
                    // notify user of the new issue ID
                    DialogMessage dialogMessage = new DialogMessage(
                                this,
                                CommonResources.NewIssueCreatedText + _issueVisionModel.CurrentEditIssue.IssueID,
                                null)
                    {
                        Button = MessageBoxButton.OK,
                        Caption = CommonResources.NewIssueCreatedCaption
                    };

                    AppMessages.StatusUpdateMessage.Send(dialogMessage);

                    // save is successful, start another new issue
                    CurrentIssue = AddNewIssue();
                    AppMessages.EditIssueMessage.Send(CurrentIssue);
                }
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for PropertyChanged
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("HasChanges"))
            {
                SubmitChangeCommand.RaiseCanExecuteChanged();
                CancelChangeCommand.RaiseCanExecuteChanged();
            }
        }
        
        #endregion "Private Methods"
    }
}